package com.umfwechat.lightprogram.controller.sys;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.umfwechat.common.code.RetCode;
import com.umfwechat.common.constant.CacheConsts;
import com.umfwechat.common.constant.CommonConsts;
import com.umfwechat.common.constant.ConfigConsts;
import com.umfwechat.common.constant.ValueConsts;
import com.umfwechat.common.prop.UmfPropModel;

import com.umfwechat.util.HttpUtil;
import com.umfwechat.util.JsonUtil;
import com.umfwechat.util.MessageDigestUtil;
import com.umfwechat.util.RedisUtil;
import com.umfwechat.util.ReqMessageUtil;
import com.umpay.sp.model.common.ReqMessage;
import com.umpay.sp.model.common.ResMessage;
import com.umpay.sp.model.saas.AgentPerm;
import com.umpay.sp.model.saas.OperplatRel;
import com.umpay.sp.service.saas.remote.AgentPermServiceRemote;
import com.umpay.sp.service.saas.remote.OperPlatRelServiceRemot;

@Controller
@RequestMapping("/autoLogin")
public class AutoLogin {
	private static Logger logger = LoggerFactory.getLogger(AutoLogin.class);
	@Resource
	private  OperPlatRelServiceRemot operPlatRelServiceRemot;
	@Resource
	private AgentPermServiceRemote agentPermServiceRemote;
	@RequestMapping(value="/loginOn",produces="application/json;charset=UTF-8")
	@ResponseBody
	public JSONObject loginOn(HttpServletRequest req,HttpServletResponse resp){
		JSONObject json= new JSONObject();
		json.put(CommonConsts.RETCODE, RetCode.SUCCESS);
		json.put(CommonConsts.RETMSG, "成功");
		//获取前台传入的参数:token,code
		String reqJSON=  (String) req.getAttribute(CommonConsts.REQUESTDATA); 
		JSONObject param=JSONObject.fromObject(reqJSON);
		String loginToken=param.optString(CommonConsts.TOKEN);
		String code =(String)param.get(CommonConsts.CODE);
		String userId =null;
		String agentId = null; 
		String assistId = null; 
		String password=ValueConsts.LOGIN_PASSWD;//初始密码
		String rValue=null;
		try {
			logger.info("扫码入参loginToken="+loginToken);
			rValue = RedisUtil.get(loginToken);
			logger.info("自动登陆redis出参"+rValue);
		} catch (Exception e2) {
			logger.info("【自动登陆接口】=========自动登陆接口=========="+"redis服务器异常："+e2);
			json.put(CommonConsts.RETCODE, "0001");
			json.put(CommonConsts.RETMSG, "请求失败，稍后重试");
			return  json;
		}
		if(rValue != null){
			String[] values = rValue.split("\\|");
			userId=values[0];
			agentId = values[1];
			assistId=values[2];
		}else{
			json.put(CommonConsts.RETCODE, "00434106");
			json.put(CommonConsts.RETMSG, "二维码已被扫");
			return  json;
		}
		String xcxAppid=UmfPropModel.INSTANCE.getPropValue(ConfigConsts.XCXAPPID);
		String xcxSecret=UmfPropModel.INSTANCE.getPropValue(ConfigConsts.XCXSECRET);
		// 设置向微信发送请求生成openId时的参数
		StringBuffer sb = new StringBuffer();
		sb.append("?appid="+xcxAppid);
		sb.append("&secret="+xcxSecret);
		sb.append("&js_code="+code);
		sb.append("&grant_type=authorization_code");
		// 向微信发送请求
		String create_openId_url=UmfPropModel.INSTANCE.getPropValue(ConfigConsts.CREATE_OPENID_URL);
		String openIdRes = null;
		try {
			logger.info("【调用微信登陆接口】=========登陆接口=========="+"调用微信登陆接口入参："+sb.toString()+"url:"+create_openId_url);
			openIdRes = HttpUtil.doGet(create_openId_url,sb.toString(), CommonConsts.UTF8, true);
			logger.info("【调用微信登陆接口】=========登陆接口=========="+"调用微信登陆接口出参："+openIdRes);
		} catch (Exception e1) {
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			logger.info("【调用微信登陆接口】=========登陆接口=========="+"调用微信登陆接口异常：",e1);
			return json;
		}
		Map<String, Object> openIdMap = JsonUtil.parseJSON2Map(openIdRes);
		// 判断返回值的key中是否有"openid"
		if(!openIdMap.containsKey(CommonConsts.OPENID)){ 
			// 获取微信请求失败
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return json;
		}
		String openId=(String)openIdMap.get(CommonConsts.OPENID);
		//进行登陆
		Map<String, Object> resLogin=queryAgentManager(assistId,userId);
		String retCodeLogin=(String)resLogin.get("retCode");
		if(!"0000".equals(retCodeLogin)){
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return json;
		}
		List<Map> list=(List<Map>)resLogin.get("agentManagerList");
		if(list.size()==0){
			json.put(CommonConsts.RETCODE, "00434104");
			json.put(CommonConsts.RETMSG, "登陆账号不存在");
			return json;
		}
		Map map = list.get(0);
		Object state = map.get("state");
		if("0".equals(state)){
			json.put(CommonConsts.RETCODE, "00434113");
			json.put(CommonConsts.RETMSG, "该账号已经被代理商设置为停用");
			return json;
		}
		Object passwordDb = map.get("password");
		String digest;
		try {
			digest = MessageDigestUtil.digest(password);
			logger.info("登陆密码加密后的结果"+digest);
		} catch (NoSuchAlgorithmException e) {
			logger.info("密码加密异常",e);
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return json;
		}
		//比对密码是否相等
		if(!digest.equals(passwordDb)){
			json.put(CommonConsts.RETCODE, "00434102");
			json.put(CommonConsts.RETMSG, "登录账号或密码不正确");
			return json;
		}
		//登陆成功后，调代理商基本信息接口，获取可以代理商的产品
		//查询代理商基本信息
		Map<String, Object> res=getAgentByPrimaryKey(agentId,"0");
		String retCode=(String)res.get("retCode");
		if(!"0000".equals(retCode)){
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return json;
		}
		Map<String ,Map<String ,String>> agentList = (Map<String ,Map<String ,String>>) res.get("agentMap");
		Map<String ,String> agentData = agentList.get(agentId);
		Object productAttribute = agentData.get("agreementType");
		if(productAttribute==null || "".equals(productAttribute)){
			logger.info("没有可代理的产品属性productAttribute="+productAttribute);
			json.put(CommonConsts.RETCODE, "00434105");
			json.put(CommonConsts.RETMSG, "登陆失败");
			return json;
		}
		// 查询外部用户关系
		//查询参数
		ReqMessage reqMsg =ReqMessageUtil.makeSpReq();
		reqMsg.put(CommonConsts.AGENTID, agentId);
		reqMsg.put(CommonConsts.STATE, ValueConsts.STATE_TWO);
		reqMsg.put(CommonConsts.USERID, userId);
		ResMessage queryUserResMsg = null;
		try {
			logger.info("【查询外部用户关系接口】=========登陆接口=========="+"查询外部用户关系接口入参："+reqMsg.toString());
			queryUserResMsg = operPlatRelServiceRemot.getOperPlatRels(reqMsg);
			logger.info("【查询外部用户关系接口】=========登陆接口=========="+"查询外部用户关系接口出参："+queryUserResMsg.toString());
		} catch (Exception e) {
			logger.info("【查询外部用户关系接口】=========登陆接口=========="+"查询外部用户关系接口",e);
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return json;
		}
		// 判断是否成功获取查询数据
		String retCodeQ = queryUserResMsg.getRetCode();
		if (!RetCode.SUCCESS.equals(retCodeQ)) {
			json.put(CommonConsts.RETCODE, "00434101");
			json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return json;
		}
		// 判断Map是否长度大于0
		List<OperplatRel> operplatRels=(List<OperplatRel>)queryUserResMsg.getValue("operPlatRels");
		if (operplatRels.size()>0) {
			//openid与数据库中的一致，说明换微信登陆了，就更新绑定
			OperplatRel o=operplatRels.get(0);
			if (!o.getExternaluserid().equals(openId)) {
				//openid与数据库中的一致，说明换微信登陆了，就更新绑定
				ResMessage updateUser =updaterOperPlatRel(agentId,userId,openId);
				// 更新成功
				if (!updateUser.getRetCode().equals(RetCode.SUCCESS)) {								
					json.put(CommonConsts.RETCODE, "00434101");
					json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
					return json;
				} 
			}
		}else {
			ResMessage bindUser =saveOperPlatRel(agentId,ValueConsts.STATE_TWO,userId,openId);
			if (!bindUser.getRetCode().equals(RetCode.SUCCESS)) {
				json.put(CommonConsts.RETCODE, "00434101");
				json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
				return json;
			}
		}
		if(userId.equals(CommonConsts.ADMIN)){
			json.put(CommonConsts.USERTYPE,ValueConsts.TYPE_ONE);					
		}else{
			//业务员需要查询权限
			json.put(CommonConsts.USERTYPE,ValueConsts.TYPE_TWO);
			//业务员需要查询权限
			ResMessage resP = getAgentPermByPri(agentId,assistId,userId);
			if (!RetCode.SUCCESS.equals(resP.getRetCode())) {
				json.put(CommonConsts.RETCODE, "00434101");
				json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
				return json;
			}
			AgentPerm agentPerm=(AgentPerm)resP.getValue("agentPerm");
			if (agentPerm==null) {
				json.put(CommonConsts.RETCODE, "00434101");
				json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
				return json;
			}
			String searchStorePerm=agentPerm.getSearchStorePerm();
			String fetchBillDocPerm=agentPerm.getFetchBillDocPerm();
			String searchProfitPerm=agentPerm.getSearchProfitPerm();
			List<String> sp = new ArrayList<String>();
			if("1".equals(searchStorePerm)){
				sp.add("searchStorePerm");
			}
			if("1".equals(fetchBillDocPerm)){
				sp.add("fetchBillDocPerm");
			}
			if("1".equals(searchProfitPerm)){
				sp.add("searchProfitPerm");
			}
			json.put("permissionConf", sp);
			//把权限存在缓存中,
			try {
				RedisUtil.set(CacheConsts.PERMISSIONCONF+agentId+userId, ValueConsts.THIRTY_DAY, sp.toString());
			} catch (Exception e) {
				json.put(CommonConsts.RETCODE, "00434101");
				json.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
				return json;
			}
		}
		// 自生成uuid作为token，并将生成的token传至前台
		String token = UUID.randomUUID().toString();
		RedisUtil.set(CacheConsts.LOGIN+agentId+userId, ValueConsts.THIRTY_DAY, userId+","+assistId+","+password+","+token);
		logger.info("=========登陆接口=========="+"设置：缓存中key为："+CacheConsts.LOGIN+agentId+userId+"缓存中value为"+ userId+","+assistId+","+password+","+token);
		json.put("token", token);
		json.put(CommonConsts.USERID, userId);
		json.put(CommonConsts.AGENTID, agentId);
		json.put(CommonConsts.AGENTNAME, agentData.get("agentShortName"));
		// 代理商类型，即代理商级别
		json.put(CommonConsts.AGENTYPE, agentData.get("agentLevel"));
		json.put(CommonConsts.PRODUCTATTRIBUTE, productAttribute);// 代理商登录时返回的字段:productAttribute=1 仅是SAAS产品时. 开通产品页面隐藏开通POS,其他值都显示.
		json.put(CommonConsts.ASSISTID, assistId);
		json.put("agentLevel", agentData.get("agentLevel"));
		RedisUtil.del(loginToken);
		return json;
	}
	private ResMessage getAgentPermByPri(String agentId, String assistId, String userId) {
		ReqMessage req=ReqMessageUtil.makeSpReq();
		req.put("agentId", agentId);
		req.put("assistId", assistId);
		req.put("salesmanId", userId);
		ResMessage res =null;
		try {
			logger.info("【查询业务员权限接口】入参"+req.toString());
			res = agentPermServiceRemote.getAgentPermByPri(req);
			logger.info("【查询业务员权限接口】出参"+res);
		} catch (Exception e) {
			logger.info("【调用外部用户关系保存接口】=========登陆接口=========="+"调用外部用户关系保存接口异常",e);
			res.put(CommonConsts.RETCODE, "0001");
			res.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return res;
		}
		return res;
	}
	private ResMessage saveOperPlatRel(String agentId, String state, String userId, String openId) {
		//绑定参数
		ReqMessage  bindReqMsg=ReqMessageUtil.makeSpReq();
		//设置绑定用户关系的请求参数
		Map<String, String> bindUserReq = new HashMap<String, String>();		
		bindUserReq.put(CommonConsts.AGENTID, agentId);
		bindUserReq.put(CommonConsts.STATE, state);	//2-正常;4-注销
		bindUserReq.put(CommonConsts.USERID, userId);
		bindUserReq.put(CommonConsts.OPEN_ID, openId);
		bindUserReq.put(CommonConsts.EXTERNALWEB,CommonConsts.WX);
		bindUserReq.put(CommonConsts.ADDUSER,userId);
		bindUserReq.put(CommonConsts.MODUSER,userId);
		bindReqMsg.setReqMap(bindUserReq);
		ResMessage bindUser =null;
		try {
			// 如果获取的外在关系中的map为空
			logger.info("【调用外部用户关系保存接口】=========登陆接口=========="+"调用外部用户关系保存接口入参"+bindReqMsg.toString());
			bindUser = operPlatRelServiceRemot.saveOperPlatRel(bindReqMsg);
			logger.info("【调用外部用户关系保存接口】=========登陆接口=========="+"调用外部用户关系保存接口出参"+bindUser.toString());
		} catch (Exception e) {
			logger.info("【调用外部用户关系保存接口】=========登陆接口=========="+"调用外部用户关系保存接口异常",e);
			bindUser.put(CommonConsts.RETCODE, "00434101");
			bindUser.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return bindUser;
		}
		return bindUser;
	}
	private ResMessage updaterOperPlatRel(String agentId, String userId,
			String openId) {
		//更新参数
		ReqMessage  updateReqMsg= ReqMessageUtil.makeSpReq();
		updateReqMsg.put(CommonConsts.AGENTID, agentId);
		updateReqMsg.put(CommonConsts.USERID, userId);
		updateReqMsg.put(CommonConsts.OPEN_ID, openId);
		// 查询外部用户关系
		ResMessage updateUser = null;
		try {
			logger.info("【调用外部用户关系更新接口】=========登陆接口=========="+"调用外部用户关系更新接口入参"+updateReqMsg.toString());
			updateUser = operPlatRelServiceRemot.updaterOperPlatRel(updateReqMsg);
			logger.info("【调用外部用户关系更新接口】=========登陆接口=========="+"调用外部用户关系更新接口出参"+updateUser.toString());
		} catch (Exception e) {
			logger.info("【查询外部用户关系接口】=========登陆接口=========="+"查询外部用户关系接口",e);
			updateUser.put(CommonConsts.RETCODE, "00434101");
			updateUser.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return updateUser;
		}
		return updateUser;
	}
	//查询代理商管理员信息
	private Map<String, Object> queryAgentManager(String assistId, String userName) {
		Map<String, Object> reqLogin = ReqMessageUtil.makeReqCrmMap();
		reqLogin.put("id", assistId);
		reqLogin.put("userName", userName);
		Map<String, Object> resLogin = null;
		try {
			XStream xstream = new XStream(new DomDriver());
			// URL配置文件取		
			String url=UmfPropModel.INSTANCE.getPropValue("agent.crm.queryAgentManager");
			logger.info("【查询代理商管理员信息】接口入参："+reqLogin.toString()+"请求路径为"+url);
			resLogin = (Map<String, Object>) com.umfwechat.util.HttpUtil.getResObjPost(url, xstream, reqLogin);
		} catch (Exception e) {
			logger.info("查询代理商管理员信息接口异常",e);
			resLogin.put(CommonConsts.RETCODE, "00434101");
			resLogin.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return resLogin;
		}
		if(resLogin==null){
			resLogin.put(CommonConsts.RETCODE, "00434101");
			resLogin.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return resLogin;
		}
		logger.info("【查询代理商管理员信息】接口出参："+resLogin.toString());
		return resLogin;
	}
	//查询代理商基本信息
	private Map<String, Object> getAgentByPrimaryKey(String agentId,
			String isQryMer) {
		Map<String, Object> req = ReqMessageUtil.makeReqCrmMap();
		req.put("agentId", agentId);
		//是否附带直拓商户信息0-不查询,1-查询
		req.put("isQryMer", "0");
		Map<String, Object> res = null;
		try {
			XStream xstream = new XStream(new DomDriver());
			// URL配置文件取		
			String url=UmfPropModel.INSTANCE.getPropValue("agent.crm.queryAgent");
			logger.info("【根据主键查询代理商详情】接口入参："+req.toString()+"请求路径为"+url);
			res = (Map<String, Object>) com.umfwechat.util.HttpUtil.getResObjPost(url, xstream, req);
		} catch (Exception e) {
			logger.info("查询代理商列表server接口异常",e);
			res.put(CommonConsts.RETCODE, "00434101");
			res.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return res;
		}
		if(res==null){
			res.put(CommonConsts.RETCODE, "00434101");
			res.put(CommonConsts.RETMSG, "服务器异常，请稍后再试");
			return res;
		}
		logger.info("【根据主键查询代理商详情】接口出参："+res.toString());
		return res;
	}
}